package de.clue.corpus.twitter.reader;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
import java.io.Writer;
import java.util.Iterator;
import java.util.Vector;

import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

import org.xml.sax.Attributes;
import org.xml.sax.SAXException;

/**
 * 
 * Read again corpus files an process them using different classes.
 * 
 * @author asuslova
 *
 */
public class GenericSaxFileReader extends org.xml.sax.helpers.DefaultHandler{

    private boolean foundText;
    private StringBuffer xmlStringCache = new StringBuffer();
    private StringBuffer cachedText = new StringBuffer();
    private Writer out;
    private final String path;
    private final String outputPath;
    private final Vector<ITextWorker> textWorkers;
    private final Vector<IElementAppender> appender;
    


    public GenericSaxFileReader(String path, String outputPath, Vector<ITextWorker> workers, Vector<IElementAppender> appender) throws Exception {
        this.path = path;
        this.outputPath = outputPath;
        this.textWorkers = workers;
        this.appender = appender;

        validateArguments();

    }

    private void validateArguments() {

        if(outputPath == null){
            throw new IllegalArgumentException("outputPath must not be empty!");
        }

        File toCheck = new File(outputPath);
        if(!toCheck.exists()){
            toCheck.mkdirs();
            if(!toCheck.exists()) {
                throw new IllegalArgumentException("outputPath can not be created!");

            }
        }

        if(path == null){
            throw new IllegalArgumentException("path must not be empty!");
        }

        toCheck = new File(path);
        if(!toCheck.exists()){
            throw new IllegalArgumentException("path must exist!");
        }


    }

    public void process(){
        processFilesInDirectory();

    }


    private void processFilesInDirectory() {
        File sourceDirectory = new File(path);
        String[] list = sourceDirectory.list();

        for (int i = 0; i < list.length; i++) {
            try {
                String currentFileName = list[i];
                File currentFile = new File(path,currentFileName);
                if(currentFile.isFile()){
                    System.out.println("Processing file: " + currentFile.getAbsolutePath());

                    try {
                        out = new BufferedWriter(new OutputStreamWriter(
                                new FileOutputStream(outputPath + System.getProperty("file.separator") + currentFileName), "UTF8"));

                        out.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
                        out.write(System.getProperty("line.separator"));

                    } catch (UnsupportedEncodingException e) {
                        e.printStackTrace();
                    } catch (FileNotFoundException e) {
                        e.printStackTrace();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }

                    readFile(currentFile);

                    try {
                        out.flush();
                        out.close();
                        out = null;
                    } catch (Exception e) {
                        e.printStackTrace();
                    }

                    System.out.println("File processed!");

                }
            } catch (Exception e) {
                e.printStackTrace();

            }

        }

    }


    private void readFile(File file) throws Exception{

        // Factory um parser zu erzeugen
        SAXParserFactory factory = SAXParserFactory.newInstance();
        // Parser um datei zu parsen
        SAXParser saxParser = factory.newSAXParser();

        // Parse Datei; Parameter sind: Dateiname und Handler
        saxParser.parse(file, this);

    }


    public void startElement(String uri, String localName, String qName,
            Attributes attributes) throws SAXException {

        if (qName.equalsIgnoreCase("root")) {
            //      System.out.println(">>>> START <<<<<<<");
        }

        if (qName.equalsIgnoreCase("tweet")) {
            // System.out.println(" ### Tweet ###");
        }
        if (qName.equalsIgnoreCase("text")) {
            foundText = true;
        }


        xmlStringCache.append("<" + qName + ">");

    }

    public void endElement(String uri, String localName, String name)
            throws SAXException {


        xmlStringCache.append("</" + name + ">");
        
        // hinzufuegen von elementen -> polarity!
        if("text".equals(name)){
            foundText = false;

            String text = cachedText.toString();
            cachedText = new StringBuffer();
            // Process text HERE
            for (Iterator iterator = appender.iterator(); iterator.hasNext();) {
                IElementAppender appender = (IElementAppender) iterator.next();

                appender.process(xmlStringCache,text);
                
            }
            
        }


        appendToFile(xmlStringCache.toString());
        xmlStringCache = null;
        xmlStringCache = new StringBuffer();

    }

    public void characters(char[] ch, int start, int length) throws SAXException {

        // den Text des Elements
        String text = new String(ch, start, length);

        if (foundText){
            cachedText.append(text);
            
            // text anpassen, normalisieren
            for (Iterator iterator = textWorkers.iterator(); iterator.hasNext();) {
                ITextWorker worker = (ITextWorker) iterator.next();

                text = worker.process(text);
                
            }


        }

        text = escapeText(text);
        xmlStringCache.append(text);
    }


    private String escapeText(String text){
        String escapedText = "";

        escapedText = text.replaceAll("&", "&amp;");
        escapedText = escapedText.replaceAll("\\<", "&lt;");
        escapedText = escapedText.replaceAll("\\>", "&gt;");
        escapedText = escapedText.replaceAll("\"", "&quot;");
        escapedText = escapedText.replaceAll("'", "&apos;");

        //      escapedText = StringEscapeUtils.escapeXml(text);


        return escapedText;

    }

    private void appendToFile(String text) {

        try {

            out.write(text);
            //          out.write(System.getProperty("line.separator"));
        } catch (UnsupportedEncodingException e) {
        } catch (IOException e) {
        } 

    }


}
